#pragma once
#include <boost/tokenizer.hpp>
#include <set>

namespace html { namespace dom
{
  using namespace boost;

  struct node;

  /// @brief CSS-like selector criteria that can be initialized by CSS-styled
  /// selector strings like "div.footer" or "span#subtitle" which MAY start 
  /// with a tag name that MAY be followed by a dot and a class name or 
  /// a hash mark and an id name
  struct criteria {

    /// @brief initializes criteria with a CSS-like selector string
    criteria(const string& _select) { parse(_select); }
    /// @brief tests a node's properties to match this criteria
    /// @return true, if node matches criteria else false
    inline bool operator==(const node& _node) const;
    /// @brief parse a CSS-like selector string that includes one criteria
    void parse(const string& _select) {
      // small state for remembering if we got a . or #
      enum { f_tag, f_class, f_id } state=f_tag;
      // tokenize string for . or #
      tokenizer<char_separator<char> > tok(_select,char_separator<char>("","#."));
      for (tokenizer<char_separator<char> >::iterator it=tok.begin(); it!=tok.end(); ++it) {
        // check if the current token is a . or # and set state
        switch( (*it)[0] ) {
        case '#': state=f_id; break;
        case '.': state=f_class; break;
        default:
          // add the token to either the id_, classes_ or tag_ member
          switch( state ) {
          case f_id: id_=*it; break;
          case f_class: classes_.insert(*it); break;
          case f_tag: tag_=*it; break;
          }
          state=f_tag;
        }
      }
    }
  private:
    /// @brief stored tag symbol
    symbol tag_;
    /// @brief stored id symbol
    symbol id_;
    /// @brief stored class symbols
    set<symbol> classes_;
  };
} }
